<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */


namespace app\index\service;

use app\index\model\Order;
use app\index\model\User;
use app\index\model\UserCoupon;
use app\index\service\UserCouponService;
use app\index\util\Redis;
use think\Exception;
use think\exception\InvalidArgumentException;

class OrderCouponService
{
    public function __construct()
    {
        global $user;
        $this->user = User::find($user['id']);
        $this->redis = Redis::getInstance();
    }

    public function orderUserCoupon($orderCoupon, $orderList, $couponId = [], $money = 0)
    {
       return $this->couponMoney($money, $orderList, $couponId, $orderCoupon);
    }

    private function couponMoney(&$money, $orderList, $couponId, $orderCoupon)
    {
        if (!empty($couponId)) {
            $couponMoney = $this->coupon($couponId, $orderList, $money);
            $money = bcsub((string)$money, (string)$couponMoney);
        }

        if (!empty($orderCoupon)) {
            foreach ($orderCoupon as $k => $v) {
                if (!in_array($k, $orderList))
                    throw new InvalidArgumentException("优惠券不在提交的订单列表内", HTTP_FORBIDDEN);
                $orderCouponMoney = $this->orderCoupon($v, $k);
                Order::where('order_no',$k)->update(['discount'=>$orderCouponMoney]);
                $money = bcsub((string)$money, (string)$orderCouponMoney);
            }
        }

        if (!empty($couponId)) {
            return $couponMoney;
        }
        return $orderCouponMoney;

    }

    private function orderCoupon($id, $order)
    {
        $userCouponService = new UserCouponService();
        list($code, $model) = $userCouponService->read($id);

        if ($code != 200)
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        //dd($model->used_type);
        if (!empty($model->used_type))
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);

        $orders = Order::where(['status' => 1, 'user_id' => $this->user->id, 'order_no' => $order])
            ->field('id,money,merchant_id')
            ->with(['orderCommodityHidden.commodityHidden'])
            ->find()->toArray();

        $money = $orders['money'];

        $commodityList = $this->getOrderCommodity($orders);
        if ($model->coupon->merchant_id != $orders['merchant_id']) {
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        }
        if ($model->coupon->conditions > $money) {
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        }

        if ($model->coupon->commodity_limit_type == 1) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $diffCommodity = array_intersect_key($commodityList, array_flip(array_diff(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 2) {
            $allowList = explode(",", $model->coupon->commodity_limit);

            $diffCommodity = array_intersect_key($commodityList, array_flip(array_intersect(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 3) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $allowList = array_map(function ($var) {
                return explode("->", $var);
            }, $allowList);
            $diffCommodity = [];
            foreach ($commodityList as $i => $j) {
                $explode = explode("->", $j['classify_id']);
                $flag = $this->arrayMatch($explode, $allowList);
                if (!$flag)
                    $diffCommodity[] = $j;
            }
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        }
        UserCoupon::update(["status" => 1, 'unified_order_no' => $order,'order_id'=>$orders['id']], ['id' => $id, 'status' => 0]);
        return $model->coupon->denomination;
    }

    private function coupon($id, $orderList, $money)
    {
        $userCouponService = new UserCouponService();
        list($code, $model) = $userCouponService->read($id);
        if ($code != HTTP_SUCCESS)
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        if ($model->merchant_id != 1 || !empty($model->used_type))
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);

        $orders = Order::where(['status' => 1, 'user_id' => $this->user->id, 'order_no' => $orderList])
            ->field('id,money')
            ->with(['orderCommodityHidden.commodityHidden'])
            ->select()->toArray();

        $commodityList = $this->getCommodity($orders);

        if ($model->coupon->conditions > $money) {
            throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
        }

        if ($model->coupon->commodity_limit_type == 1) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $diffCommodity = array_intersect_key($commodityList, array_flip(array_diff(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 2) {
            $allowList = explode(",", $model->coupon->commodity_limit);

            $diffCommodity = array_intersect_key($commodityList, array_flip(array_intersect(array_keys($commodityList), $allowList)));
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        } elseif ($model->coupon->commodity_limit_type == 3) {
            $allowList = explode(",", $model->coupon->commodity_limit);
            $allowList = array_map(function ($var) {
                return explode("->", $var);
            }, $allowList);
            $diffCommodity = [];
            foreach ($commodityList as $i => $j) {
                $classify = explode(',',$j['classify_id']);
                foreach ($classify as $v){
                    $explode = explode("->", $v);
                    $flag = $this->arrayMatch($explode, $allowList);
                    if (!$flag)
                        $diffCommodity[] = $j;
                }
            }
            $diffMoney = 0;
            foreach ($diffCommodity as $i => $j) {
                bcadd((string)$diffMoney, bcmul((string)$j['count'], (string)$j['discount']));
            }
            $money = bcsub((string)$money, (string)$diffMoney);
            if ($money < $model->coupon->conditions) {
                throw new Exception("优惠券不可用", HTTP_NOTACCEPT);
            }
        }

        $ordersId = implode(",",array_column($orders,'id'));
        UserCoupon::update(["status" => 1, 'unified_order_no' => $this->trade,'order_id'=>$ordersId], ['id' => $id, 'status' => 0]);

        return $model->coupon->denomination;
    }


    private function arrayMatch($explode, $allowList)
    {
        $flag = true;
        foreach ($allowList as $index => $item) {
            $diff = array_diff($item, $explode);
            if (empty($diff)) {
                $flag = false;
                break;
            }
        }
        return $flag;
    }

    private function getOrderCommodity(array $order)
    {
        $commodityList = [];
        foreach ($order['orderCommodityHidden'] as $i => $j) {
            $commodityList[$j['commodity_id']] = $j;
        }
        return $commodityList;
    }

    private function getCommodity(array $orders)
    {
        $commodityList = [];
        foreach ($orders as $k => $v) {
            foreach ($v['orderCommodityHidden'] as $i => $j) {
                $commodityList[$j['commodity_id']] = $j;
            }
        }
        return $commodityList;
    }

}